package com.hoshiicloud.mallshop.mq;

import com.alibaba.fastjson.JSONObject;
import com.hoshiicloud.common.constant.*;
import com.hoshiicloud.common.constant.refund.RefundOrderStatusEnum;
import com.hoshiicloud.common.constant.refund.RefundServiceTypeEnum;
import com.hoshiicloud.common.exception.ServiceException;
import com.hoshiicloud.common.rpc.Response;
import com.hoshiicloud.common.utils.EncryptionUtil;
import com.hoshiicloud.goods.entity.sku.ProductManage;
import com.hoshiicloud.goods.param.sku.ProductManageUpdateParam;
import com.hoshiicloud.mallshop.config.RsaConfig;
import com.hoshiicloud.mallshop.dto.OrderInfoAfterSaleStatusDto;
import com.hoshiicloud.mallshop.dto.OrderMainAfterSaleStatusDto;
import com.hoshiicloud.mallshop.dto.RefundRbmqJsonDto;
import com.hoshiicloud.mallshop.feign.ShopGoodsSpuSkuFeignService;
import com.hoshiicloud.mallshop.feign.ShopSaleOrderFeignService;
import com.hoshiicloud.mallshop.service.impl.aftersale.RefundManageServiceImpl;
import com.hoshiicloud.saleorder.entity.OrderInfo;
import com.hoshiicloud.saleorder.param.OrderInfoUpdateParam;
import com.hoshiicloud.saleorder.param.OrderMainUpdateParam;
import com.hoshiicloud.saleorder.param.refund.RefundOrderListParam;
import com.hoshiicloud.saleorder.vo.refund.RefundOrderVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *  2019-06-01 15:15 Mr.wu
 * rabmitMQ  退款消息消费业务处理
 */

@Slf4j
@Component
public class RefundRabbitMQConsumer {

    @Autowired
    private RsaConfig rsaConfig;

    @Autowired
    private ShopSaleOrderFeignService shopSaleOrderFeignService;
    @Autowired
    private RefundManageServiceImpl refundManageServiceImpl;

    @Autowired
    private ShopGoodsSpuSkuFeignService shopGoodsFeignService;

    /**
     * 退款成功回调消息处理
     */
    @RabbitListener(queues = QueueConsts.REFUND_CALLBACK_QUEUE)
    @RabbitHandler
    public void refundCallBackprocess(Message message) {
        try {
            log.info("聚合接受退款回调消息" + message.toString());
            //获取请求体转换
            String body = new String(message.getBody());
            log.info("body:" + body);
            System.out.println(body);
            String json = new String(Base64.getMimeDecoder().decode(body.replace("\r\n", "")));
            Map<String, String> data = EncryptionUtil
                    .decryptData(json, rsaConfig.getClientPublicKey(),
                            rsaConfig.getServerPrivateKey());
            if (data == null) {
                //验签失败
                throw new ServiceException("聚合解析退款回调消息失败，验签失败");
            } else {
                String attach =  data.get("attach");
                log.info("透传数据attach：" + data.get("attach"));
                RefundRbmqJsonDto dto = JSONObject.parseObject(attach,RefundRbmqJsonDto.class);

                //插入商家协商历史
                refundManageServiceImpl.insertConsulations(dto.getC1());
                //删除旧系统协商历史
                refundManageServiceImpl.deleteSysConsulation(dto.getRefundId());
                //插入新的系统协商历史
                refundManageServiceImpl.insertConsulations(dto.getC2());
                //这里要先执行   后面子订单状态更新 判断需要 获取该子订单所有退款成功的退款单
                refundManageServiceImpl.updateRefundOrderStatue(dto.getRefundOrderUpParam());

                //获取子订单的全部退款成功的 商品数量
                int qtys = this.getRefundSuccessNum(dto.getOrderInfoId());

                //获取子订单需要更新的状态
                OrderInfoAfterSaleStatusDto orderInfoStatus= this.getOrderInfoSomeStatus(dto.getOrderInfoQty(),
                        qtys,dto.getRefundServiceType(),dto.getOrderInfoId());

                //更新子订单  这里要先执行   后面主订单状态更新 判断需要 获取所有子订单的售后状态
                this.updateOrderInfo(dto.getOrderInfoId(),orderInfoStatus);

                //获取主订单下所有子订单信息
                List<OrderInfo> listOrderInfo = this.listOrderInfoByMainId(dto.getOrderMainId());

                //获取主订单需要更新的状态
                OrderMainAfterSaleStatusDto orderMainStatus = this.getOrderMainRefundNum(dto.getOrderMainOrderStatus(),listOrderInfo);

                //更新主订单
                this.updateOrderMain(dto.getOrderMainId(),orderMainStatus);

                //更新库存  （暂时没用上先注释掉）
                this.updateProductManage(dto.getExtSkuId(),dto.getStoreId(),dto.getRefundQty());
            }
            //业务处理
        } catch (Exception e) {
            log.error("{}", e.getMessage());
        }
    }


    /**
     *  11:40 2019/9/6 qry
     *  获取子订单需要更新的状态信息
     **/
    private OrderInfoAfterSaleStatusDto getOrderInfoSomeStatus(int orderInfoQtys, int refundQtys, int refundServiceType, Long orderInfoId){
        OrderInfoAfterSaleStatusDto orderInfoAfterSaleStatusDto = new OrderInfoAfterSaleStatusDto();

        if(orderInfoQtys == refundQtys){
            //如果子订单数量=退款的数量  子订单售后状态为售后完成
            orderInfoAfterSaleStatusDto.setServiceStatus(OrderInfoServiceStatusEnum.AFTER_COMPLETE.getCode());

            //如果子订单数量=退款的数量  子订单退款状态为全额退款
            orderInfoAfterSaleStatusDto.setRefundStatus(OrderInfoRefundStatusEnum.ALL_REFUND.getCode());

            //如果子订单数量=退款的数量   子订单订单状态为退款成功
            orderInfoAfterSaleStatusDto.setOrderStatus(OrderInfoStatusEnum.REFUND_SUCCESS.getCode());

            //如果子订单数量=退款的数量   且 售后类型 为 退货退款   子订单的退货状态为完全退货
            if(refundServiceType == RefundServiceTypeEnum.REFUND_RETURN_GOODS.getCode()){
                orderInfoAfterSaleStatusDto.setReturnGoodsStatus(OrderInfoReturnGoodStatusEnum.ALL_RETURN_GOODS.getCode());

            }
        }else{
            //如果子订单数量！=退款的数量  子订单售后状态为可以售后
            Boolean flag =  this.getAfterClose(orderInfoId);
            if(flag){
                orderInfoAfterSaleStatusDto.setServiceStatus(OrderInfoServiceStatusEnum.AFTER_THE_COMPLETION_OF.getCode());

            }else{
                orderInfoAfterSaleStatusDto.setServiceStatus(OrderInfoServiceStatusEnum.CAN_AFTER_SALE.getCode());
            }

            //如果子订单数量！=退款的数量  子订单退款状态为部分退款
            orderInfoAfterSaleStatusDto.setRefundStatus(OrderInfoRefundStatusEnum.PART_REFUND.getCode());

            //如果子订单数量！=退款的数量  且 售后类型 为 退货退款   子订单的退货状态为部分退货
            if(refundServiceType == RefundServiceTypeEnum.REFUND_RETURN_GOODS.getCode()){
                orderInfoAfterSaleStatusDto.setReturnGoodsStatus(OrderInfoReturnGoodStatusEnum.PART_RETURN_GOODS.getCode());
            }
        }


        return orderInfoAfterSaleStatusDto;
    }

    private Boolean getAfterClose(Long orderInfoId){
        Boolean flag = false ;
        Response<OrderInfo> rs = shopSaleOrderFeignService.getOrderInfoById(orderInfoId);
        if (null == rs || rs.getCode() != 200 || null == rs.getData()) {
            throw new ServiceException("获取子订单信息失败");
        }
        if(null != rs.getData().getReceivedTime()){
            LocalDateTime servenDayLater = rs.getData().getReceivedTime().plusDays(7);
            LocalDateTime now = LocalDateTime.now();
            long t = servenDayLater.toEpochSecond(ZoneOffset.of("+8")) - now.toEpochSecond(ZoneOffset.of("+8"));
            if(t <= 0){
                 flag = true;
            }
        }
        return flag;
    }


    /**
     * 11:39 2019/9/6 qry
     * 获取该子订单  退款成功的退款单的商品数量
     *
     **/
    private int getRefundSuccessNum(Long orderInfoId){
        RefundOrderListParam refundOrderListParam = new RefundOrderListParam();
        refundOrderListParam.setStatus( RefundOrderStatusEnum.REFUND_SUCCESS.getCode());
        refundOrderListParam.setSubId(orderInfoId);
        Response<List<RefundOrderVo>> refundOrderListRs  = shopSaleOrderFeignService.listRefundOrder(refundOrderListParam);
        if (null == refundOrderListRs || refundOrderListRs.getCode() != 200 || null == refundOrderListRs.getData()) {
            throw new ServiceException("获取子订单下的退款单失败");
        }
        int qtys  = 0;
        for (RefundOrderVo r:refundOrderListRs.getData()){
            qtys += r.getApplyQtys().intValue();
        }
        return qtys;
    }

    /**
     * 11:39 2019/9/6 qry
     * 更新子订单
     **/
    private void updateOrderInfo(Long orderInfoId,OrderInfoAfterSaleStatusDto orderInfoStatus){
        OrderInfoUpdateParam orderInfoParam = new OrderInfoUpdateParam();
        orderInfoParam.setId(orderInfoId);
        orderInfoParam.setServiceStatus(orderInfoStatus.getServiceStatus());
        orderInfoParam.setRefundStatus(orderInfoStatus.getRefundStatus());
        if (null != orderInfoStatus.getReturnGoodsStatus()) {
            orderInfoParam.setReturnGoodsStatus(orderInfoStatus.getReturnGoodsStatus());
        }
        if(null != orderInfoStatus.getOrderStatus()){
            orderInfoParam.setOrderStatus(orderInfoStatus.getOrderStatus());
        }
        Response<Boolean> orderInfoUpdateRs = shopSaleOrderFeignService.updateOrderInfoById(orderInfoParam);
        if (null == orderInfoUpdateRs || orderInfoUpdateRs.getCode() != 200 || null == orderInfoUpdateRs.getData()) {
            throw new ServiceException("通过子订单ID 修改子订单信息失败");
        }
    }

    /**
     *  11:47 2019/9/6 qry
     * 通过主订单ID 查询 子订单列表
     **/
    private List<OrderInfo> listOrderInfoByMainId(Long mainId){
        Response<List<OrderInfo>> orderInfoListRs = shopSaleOrderFeignService.listOrderInfoByMainId(mainId);
        if (null == orderInfoListRs || orderInfoListRs.getCode() != 200 || null == orderInfoListRs.getData()) {
            throw new ServiceException("获取主订单下所有子订单信息失败");
        }
        return orderInfoListRs.getData();
    }

    /**
     * 13:50 2019/9/6 qry
     * 获取主订单要更新的状态数据
     **/
    private OrderMainAfterSaleStatusDto getOrderMainRefundNum(int orderMainOrderStatus, List<OrderInfo> listOrderInfo){
        log.info("主订单入仓1："+orderMainOrderStatus);
        log.info("主订单入仓2："+JSONObject.toJSONString(listOrderInfo));
        OrderMainAfterSaleStatusDto rs = new OrderMainAfterSaleStatusDto();
        int allRefundOrderNum = 0 ; //全款售后 的子订单数量
        for(OrderInfo sub:listOrderInfo ){
            if(sub.getRefundStatus() == OrderInfoRefundStatusEnum.ALL_REFUND.getCode()){
                allRefundOrderNum += 1;
            }
        }
        log.info("主订单新状态：全额退款数量" + allRefundOrderNum );
        if(allRefundOrderNum == listOrderInfo.size()){
            //当 订单下 所有商品数量 等于  退款商品数量   主订单的售后状态修改为已售后
            rs.setServiceStatus(OrderMainServiceStatusEnum.ALL_AFTER_SALE.getCode());
            if(orderMainOrderStatus != OrderMainStatusEnum.SUCCESSFUL_DEAL.getCode()){
                //当 订单下 所有商品数量 等于  退款商品数量  且 主订单状态不为交易成功  主订单的状态修改为关闭交易
                rs.setOrderStatus(OrderMainStatusEnum.ORDER_CLOSED.getCode());
            }
        }else{
            rs.setServiceStatus(OrderMainServiceStatusEnum.PART_AFTER_SALE.getCode());
        }
        log.info("主订单新状态："+JSONObject.toJSONString(rs));
        return rs;
    }
    private void updateOrderMain(Long orderMainId,OrderMainAfterSaleStatusDto orderMainStatus){
        OrderMainUpdateParam orderMainUpdateParam = new OrderMainUpdateParam();
        orderMainUpdateParam.setId(orderMainId);
        if(null!=orderMainStatus.getOrderStatus()){
            orderMainUpdateParam.setOrderStatus(orderMainStatus.getOrderStatus());
        }
        if(null!=orderMainStatus.getServiceStatus()){
            orderMainUpdateParam.setServiceStatus(orderMainStatus.getServiceStatus());
        }
        Response<Boolean> orderMainUpdateRs = shopSaleOrderFeignService.updateOrderMainById(orderMainUpdateParam);
        if (null == orderMainUpdateRs || orderMainUpdateRs.getCode() != 200 || null == orderMainUpdateRs.getData()) {
            throw new ServiceException("根据主订单ID更新主订单信息失败");
        }
    }

    private void updateProductManage(Long extSkuId,Long storeId,Long qty){
        Map<String,Object> map = new HashMap<>();
        map.put("storeId",storeId);
        map.put("extSkuId",extSkuId);
        Response<ProductManage> productManageResponse = shopGoodsFeignService.getProductManageOneByStoreIdAndSkuId(map);
        if (null == productManageResponse || productManageResponse.getCode() != 200 || null == productManageResponse.getData()) {
            throw new ServiceException("获取sku分配表（productManage）失败");
        }
        ProductManageUpdateParam productManage = new ProductManageUpdateParam();
        productManage.setId(productManageResponse.getData().getId());
        productManage.setQuantity(productManageResponse.getData().getQuantity().add(new BigDecimal(qty)));
        productManage.setFreezes(productManageResponse.getData().getFreezes().subtract(new BigDecimal(qty)));
        Response<Boolean> up = shopGoodsFeignService.updateProductMangerById(productManage);
        if (null == up || up.getCode() != 200 || null == up.getData()) {
            throw new ServiceException("更新sku分配表（productManage）失败");
        }

    }



}
